package com.zy.cat.common.utils;

import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.DESKeySpec;

import org.apache.commons.lang3.StringUtils;

import lombok.extern.slf4j.Slf4j;

import java.security.SecureRandom;
import java.util.Base64;

/**  
 * @Description: DES加密解密工具类（ECB模式填充：PKCS5Padding）
 * @author xiake
 * @date 2019-12-17 10:01:17 
*/
@Slf4j
public class DESUtil {
	//密码，长度要是8的倍数    注意此处为简单密码  简单应用 要求不高时可用此密码
    private static String KEY = "Abc123.*#@%";
    
    //参数分别代表 算法名称/加密模式/数据填充方式
    private static final String ALGORITHMSTR = "DES/ECB/PKCS5Padding";
    
    /**
     *  默认编码
     */
    private static final String ENCODING_TYPE = "utf-8";

    /**
     * <p>加密</p>
     * @author lipengchao
     * @date 2019-12-10 10:34:55
     * @param datasource 需要加密的原数据
     * @param key
     * @return
     */
    private static byte[] encryptByKey(byte[] datasource, String key) {
        try {
            SecureRandom random = new SecureRandom();

            DESKeySpec desKey = new DESKeySpec(key.getBytes());
            //创建一个密匙工厂，然后用它把DESKeySpec转换成
            SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DES");
            SecretKey securekey = keyFactory.generateSecret(desKey);
            //Cipher对象实际完成加密操作 ecb模式下面的PKCS5Padding
            Cipher cipher = Cipher.getInstance(ALGORITHMSTR);
            //用密匙初始化Cipher对象
            cipher.init(Cipher.ENCRYPT_MODE, securekey, random);
            //现在，获取数据并加密
            //正式执行加密操作
            return cipher.doFinal(datasource);
        } catch (Throwable e) {
        	log.error("DES加密失败:"+e.getMessage());
//            e.printStackTrace();
        }
        return null;
    }

    /**
     * <p>加密数据然后转成Base64</p>
     * @author lipengchao
     * @date 2019-12-10 10:34:55
     * @param data 需要加密的原数据
     * @return
     */
    public static String encrypt(String data) {  
    	//对string进行BASE64Encoder转换
        byte[] bt = encryptByKey(data.getBytes(), KEY);
        String strs = new String(Base64.getEncoder().encode(bt));
        return strs;
    }
    
    /**
     * <p>加密数据然后转成Base64,自动定义Key</p>
     * @author lipengchao
     * @date 2019-12-10 10:34:55
     * @param data 需要加密的原数据
     * @return
     */
    public static String encrypt(String data,String key) {  
    	if (StringUtils.isEmpty(key)) {
    		log.error("加密key为空");
			return null;
		}
    	//对string进行BASE64Encoder转换
        byte[] bt = encryptByKey(data.getBytes(), key);
        String strs = new String(Base64.getEncoder().encode(bt));
        return strs;
    }

    /**
     * <p>解密</p>
     * @author lipengchao
     * @date 2019-12-10 10:34:55
     * @param src 加密后的密文字节数据
     * @param key 加密时用到的key
     * @return
     */
    private static byte[] decrypt(byte[] src, String key) throws Exception {
        // DES算法要求有一个可信任的随机数源
        SecureRandom random = new SecureRandom();
        // 创建一个DESKeySpec对象
        DESKeySpec desKey = new DESKeySpec(key.getBytes());
        // 创建一个密匙工厂
        SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DES");
        // 将DESKeySpec对象转换成SecretKey对象
        SecretKey securekey = keyFactory.generateSecret(desKey);
        // Cipher对象实际完成解密操作
        Cipher cipher = Cipher.getInstance(ALGORITHMSTR);
        // 用密匙初始化Cipher对象
        cipher.init(Cipher.DECRYPT_MODE, securekey, random);
        // 真正开始解密操作
        return cipher.doFinal(src);
    }

    
    /**
     * <p>解密,从Base64解密 在Des解密数据</p>
     * @author lipengchao
     * @date 2019-12-10 10:34:55
     * @param data 加密后的密文
     * @return
     */
    public static String decrypt(String data){  
    	//对string进行BASE64Encoder转换
        byte[] bt;
		try {
			bt = decrypt(Base64.getDecoder().decode(data.getBytes(ENCODING_TYPE)), KEY);
			String strs = new String(bt);
	        return strs;
		} catch (Exception e) {
			log.error("DES解密 失败:"+e.getMessage());
//			e.printStackTrace();
		}
        return null;
    }
    
    /**
     * <p>解密,通过出入key</p>
     * @author lipengchao
     * @date 2019-12-10 10:34:55
     * @param data 加密后的密文
     * @param key 加密时用到的key
     * @return
     */
    public static String decrypt(String data, String key) {
    	//对string进行BASE64Encoder转换
        byte[] bt;
		try {
			bt = decrypt(Base64.getDecoder().decode(data.getBytes(ENCODING_TYPE)), key);
			String strs = new String(bt);
	        return strs;
		} catch (Exception e) {
			log.error("DES解密 失败:"+e.getMessage());
//			e.printStackTrace();
		}
        return null;
	}

    //测试
    public static void main(String args[]) {
        //待加密内容
        String str = "wx0a8b36581832bc30";
        //加密串
        String result = DESUtil.encrypt(str,KEY);
        System.out.println("加密后：" + result);
            //直接将如上内容解密
        String decryResult = DESUtil.decrypt(result,KEY);
        if (decryResult==null) {
			System.out.println("解密失败");
		}else {
			System.out.println("解密后：" + new String(decryResult));
		}
        
    }
}
